from datetime import datetime, timedelta, time
from typing import Annotated, Literal, Union
from uuid import UUID

import uvicorn
from fastapi import FastAPI, Path, Query, Body,Cookie,Header
from fastapi.openapi.docs import get_swagger_ui_html, get_swagger_ui_oauth2_redirect_html, get_redoc_html
from starlette.staticfiles import StaticFiles
from pydantic import BaseModel, Field, HttpUrl, EmailStr

# 创建FastAPI实例，禁用掉FastAPI会自动生成Swagger UI和Redoc文档
app = FastAPI(docs_url=None, redoc_url=None)

# 静态文件挂载（路由与静态文件映射）
app.mount("/static", StaticFiles(directory="../statics"), name="static")


# 重新提供一个Swagger UI，相当于我们自己重写了这么一个路由
@app.get("/docs", include_in_schema=False)
def custom_swagger_ui():
    return get_swagger_ui_html(
        openapi_url = "/openapi.json",
        title = "Swagger UI for FastAPI",
        swagger_js_url="/static/swagger-ui-bundle.min.js",
        swagger_css_url="/static/swagger-ui.min.css"
    )
@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()

# 这里与Swagger UI一样，重新提供Redoc
@app.get("/redoc", include_in_schema=False)
def custom_redoc():
    return get_redoc_html(
        openapi_url = "/openapi.json",
        title = "Redoc for FastAPI",
        redoc_js_url="/static/redoc.standalone.js"
    )

# 基类型
class UserBean(BaseModel):
    username: str
    email: EmailStr
    full_name: str | None = None

# 输入模型
class UserIn(UserBean):
    password: str

# 输入模型
class UserOut(UserBean):
    pass

# 数据库模型
class UserInDB(UserBean):
    hashed_password: str

def fake_password_hasher(raw_password: str):
    return "supersecret" + raw_password

def fake_save_user(user_in: UserIn):
    hashed_password = fake_password_hasher(user_in.password)
    user_in_db = UserInDB(**user_in.model_dump(), hashed_password=hashed_password)
    print(f"User saved: {user_in_db}")
    return user_in_db

@app.post("/user",response_model=UserOut)
async def create_user(user_in: UserIn):
    user_saved = fake_save_user(user_in)
    return user_saved


class BaseItem(BaseModel):
    description: str
    type: str

class CarItem(BaseItem):
    type: str = "car"

class PlaneItem(BaseItem):
    type: str = "plane"
    size: int

items = {
    "item1": {"description": "this is a car description", "type": "car"},
    "item2": {"description": "this is a plane description", "type": "plane", "size": 5}
}

@app.get("/items/{item_id}", response_model=Annotated[PlaneItem | CarItem, None])
async def read_item(item_id: str):
    return items[item_id]

item_list = [
    {"description": "this is a car description", "type": "car"},
    {"description": "this is a plane description", "type": "plane", "size": 5}
]

@app.get("/items", response_model=list[Union[PlaneItem, CarItem]])
async def read_items():
    return item_list

@app.get("/scores",response_model=dict[str,float])
async def read_scores():
    return {"score1": 0.9, "score2": 0.8}

if __name__ == '__main__':
    app.debug = True
    uvicorn.run("main:app", host="127.0.0.1", port=8017, reload=True)

